package hn.cch.spring.boot.filter;

import hn.cch.spring.boot.wrapper.CustomRequestWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingResponseWrapper;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.Charset;

@Component
public class CustomRequestFilter extends OncePerRequestFilter {

    private final static Logger logger = LoggerFactory.getLogger(CustomRequestFilter.class);
    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse resp,
                                    FilterChain chain) throws IOException, ServletException {
        long start = System.nanoTime();
        CustomRequestWrapper request = new CustomRequestWrapper(req);


        StringBuilder reqBuilder = new StringBuilder();
        reqBuilder.append("Request Method: ").append(request.getMethod()).append("\n");
        reqBuilder.append("Request URI: ").append(request.getRequestURI()).append("\n");
        reqBuilder.append("Request URL: ").append(request.getRequestURL()).append("\n");
        reqBuilder.append("Request QueryString: ").append(request.getQueryString()).append("\n");

        HttpHeaders headers = (new ServletServerHttpRequest(request)).getHeaders();
        reqBuilder.append("Request Headers: ").append(headers).append("\n");
        ServletInputStream servletInputStream = request.getInputStream();
        String body = StreamUtils.copyToString(servletInputStream, Charset.defaultCharset());
        reqBuilder.append("Request Body: ").append(body).append("\n");
        logger.info("Request: \n{}", reqBuilder);

        ContentCachingResponseWrapper response = new ContentCachingResponseWrapper(resp);
        chain.doFilter(request, response);

        StringBuilder respBuilder = new StringBuilder();
        respBuilder.append("Response Status: ").append(response.getStatus()).append("\n");
        String responseBody = new String(response.getContentAsByteArray(), response.getCharacterEncoding());
        respBuilder.append("Response Content: ").append(responseBody).append("\n");
        logger.info("Response: \n{}", respBuilder);
        response.copyBodyToResponse();

        long end = System.nanoTime();
        logger.info("Processed Time: {} ms", (end - start) * 1.0 / 1000000);
    }
}
